package ejercicio.practica5;

import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;

class Dekker extends Thread {

    static int quiereEntrar = 0;
    volatile boolean flags[];
    volatile int id;
    static int N;

    public Dekker(int i, int n) {
        id = i;
        N = n;
        flags = new boolean[N];
    }

    private int random() {
        Random rm = new Random();
        return rm.nextInt(N);
    }

    private void ocupado() {
        Random rm = new Random();
        try {
            sleep(rm.nextInt(500));
        } catch (InterruptedException ex) {
            Logger.getLogger(Dekker.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void SeccionNoCritica() {
        System.out.println("Proceso " + id + " está en la región no critica");
        ocupado();
    }

    private void SeccionCritica() {
        System.out.println("Proceso " + id + " entrado en la sección critica");
        ocupado();
        System.out.println("Proceso " + id + " saliendo de la sección critica");
    }

    private boolean espera(int i) {
        boolean restoProcesos = false;

        for (int j = 0; j < N; j++) {
            if (j != i) {
                restoProcesos = restoProcesos | flags[j]; //Se comprueban el resto de procesos si están ejecutándose
            }
        }

        return restoProcesos;
    }

    private void algoDekker() {
        do {
            if (quiereEntrar != id) {
                flags[id] = false;
            }
            do {
            } while (quiereEntrar != id);
            flags[id] = true;
        } while (espera(id)); 
    }

    private void postDekker() {
        flags[id] = false;
        quiereEntrar = random();
    }

    public void run() {
        for (int i = 0; i < N; i++) {
            flags[i] = false;
        }
        do {
            SeccionNoCritica();
            algoDekker();
            SeccionCritica();
            postDekker();
        } while (true);
    }
}

class AlgDekker {

    static int N = 3;    // Número de procesos

    public static void main(String[] args) throws InterruptedException {

        Dekker p[] = new Dekker[N];

        // Lanzamiento de los hilos/procesos
        for (int i = 0; i < N; i++) {
            p[i] = new Dekker(i, N);
            p[i].start();
        }
    }
}
